package game;
import java.awt.Point;
import java.util.Observable;
import java.util.Timer;
import java.util.Set;
import java.util.HashSet;

/**
 * Creates a new instance of the game state once the player chooses their desired game.
 * It tracks the game state throughout the entirety of the game. It also swaps the pieces
 * and checks that moves are valid according to the pattern the current piece being moved.
 * 
 * @author Nicole Waldrum
 * @date January 30, 2010
 * @version 1.0
 * 
 * @author Mark Kelly
 * @date February 24, 2010
 * @version 2.0
 * 
 * @author Trevor Bastian
 * @date February 23, 2010
 * @version 2.0
 * 
 */
public class GameState implements MoveChecker, GameStateListener {
	private ChessBoard board;
	private Timer timer;
	private int turnLength;
	public GameType gameType;
	private Set<MoveChecker> moveCheckers;
	private Set<GameStateListener> gameStateListeners;
	private Set<OutcomeListener> outcomeListeners;

	/**
	 * creates a new instance of gameState.
	 * @param gameType the type of game that the player has selected
	 */
	public GameState (GameType gameType) {
		moveCheckers = new HashSet<MoveChecker>();
		gameStateListeners = new HashSet<GameStateListener>();
		outcomeListeners = new HashSet<OutcomeListener>();
		
		this.gameType = gameType;
		gameType.setGameState(this);
		gameType.setupBoard();
		
		addMoveChecker(board);
		addMoveChecker(gameType);
		
		turnLength = 0;
	}

	public GameType getGameType() {
		return gameType;
	}

	/**
	 * 
	 * @param board
	 */
	public void setBoard(ChessBoard board) {
		this.board = board;
	}
	
	/**
	 * 
	 * @return the <tt>ChessBoard</tt> that belongs to this <tt>GameState</tt>
	 */
	public ChessBoard getBoard() {
		return board;
	}

	/**
	 * Add a <tt>MoveChecker</tt> to this <tt>GameState</tt>
	 * 
	 * @param mc the <tt>MoveChecker</tt> to add
	 */
	public void addMoveChecker(MoveChecker mc) {
		moveCheckers.add(mc);
	}
	
	/**
	 * Removes a <tt>MoveChecker</tt> from this <tt>GameState</tt>
	 * 
	 * @param mc the <tt>MoveChecker</tt> to remove
	 */
	public void removeMoveChecker(MoveChecker mc) {
		moveCheckers.remove(mc);
	}
	
	/**
	 * Verifies validity of a move with every <tt>MoveChecker</tt> that has associated itself with this <tt>GameState</tt>
	 * 
	 * @param piece the <tt>Piece</tt> that will move
	 * @param point the new location of the <tt>Piece</tt>
	 * 
	 * @return <tt>true</tt> if every <tt>MoveChecker</tt> returns <tt>true</tt>
	 */
	@Override
	public boolean isValidMove(Piece piece, Point point) {
		for (MoveChecker mc : moveCheckers)
			if (!mc.isValidMove(piece, point))
				return false;
		
		return (piece.isValidMove(piece, point));
	}
	
	/**
	 * Add a <tt>GameStateListener</tt> to this <tt>GameState</tt>
	 * 
	 * @param gsl the <tt>GameStateListener</tt> to add
	 */
	public void addGameStateListener(GameStateListener gsl) {
		gameStateListeners.add(gsl);
	}
	
	/**
	 * Remove a <tt>GameStateListener</tt> from this <tt>GameState</tt>
	 * 
	 * @param pml the <tt>GameStateListener</tt> to remove
	 */
	public void removeGameStateListener(GameStateListener gsl) {
		gameStateListeners.remove(gsl);
	}
	
	/**
	 * Notify all <tt>GameStateListener</tt> that a <tt>Piece</tt> has moved
	 * 
	 * @param p the <tt>Piece</tt> that moved
	 */
	public void notifyPieceMoved(Piece p)
	{
		for (GameStateListener gsl : gameStateListeners)
			gsl.pieceMoved(p);
	}
	
	/**
	 * Add an <tt>OutcomeListener</tt> to this <tt>GameState</tt>
	 * 
	 * @param ol the <tt>OutcomeListener</tt> to add
	 */
	public void addOutcomeListener(OutcomeListener ol) {
		outcomeListeners.add(ol);
	}
	
	/**
	 * Remove an <tt>OutcomeListener</tt> from this <tt>GameState</tt>
	 * 
	 * @param ol the <tt>OutcomeListener</tt> to remove
	 */
	public void removeOutcomeListener(OutcomeListener ol) {
		outcomeListeners.remove(ol);
	}
	
	/**
	 * Notify each <tt>OutcomeListener</tt> that the game has been won
	 * 
	 * @param team the <tt>Team</tt> that won
	 */
	public void notifyGameWon(Team team)
	{
		for (OutcomeListener ol : outcomeListeners) {
			ol.gameWon(team);
		}
	}

	@Override
	public void gameStarted() {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void pieceMoved(Piece p) {
		notifyPieceMoved(p);		
	}
}